#include "StdAfx.h"
#include "Protocol.h"
#include "stddef.h"
#include "limits.h"
#include "stdlib.h"

#define BEGIN_STR "QXY"
#pragma pack(push,1)

struct MyPackHead
{
	char acBegin[4];
	BOOL bDecode;
	BOOL bZip;
	int iRand;
	int iLength;
	BYTE byCheck;
	BYTE byReserved[11];

	MyPackHead()
	{
		ZeroMemory(this,sizeof(*this));
	}
};

#pragma pack(pop)

char g_szBuf[MAX_DATA_LEN] = {0};

MYEXPORT BYTE MYAPI CalCheck( const char* pcData,int iLen )
{
	if (pcData == NULL || iLen <= 0)
	{
		return 0;
	}

	BYTE byResult = 0;
	for (int i = 0;i < iLen;i++)
	{
		byResult ^= (BYTE(pcData[i]));
	}

	return byResult;
}

MYEXPORT BOOL MYAPI CheckHead( const char* pcData,int iLen )
{
	if (pcData == NULL || iLen <= 0)
	{
		return FALSE;
	}

	if (iLen < sizeof(MyPackHead))
	{
		return FALSE;
	}

	const MyPackHead* pkHead = (const MyPackHead*)pcData;
	char acBegin[4] = BEGIN_STR;
	if (memcmp(pkHead->acBegin,acBegin,sizeof(pkHead->acBegin)) != 0)
	{
		return FALSE;
	}

	if (pkHead->byCheck != CalCheck(pcData,offsetof(MyPackHead,byCheck)))
	{
		return FALSE;
	}

	return TRUE;
}

MYEXPORT BOOL MYAPI PackMsg( MyDataPack& rkPack,const char* pcData,int iLen,BOOL bEncode /*= FALSE*/,BOOL bZip /*= FALSE*/ )
{
	if (pcData == NULL || iLen <= 0)
	{
		return FALSE;
	}

	if (iLen > MAX_MSG_LEN)
	{
		return FALSE;
	}

	static char acBuf[MAX_MSG_LEN * 2];

	MyPackHead* pkHead = (MyPackHead*)rkPack.acData;
	ZeroMemory(pkHead,sizeof(MyPackHead));	
	
	const char* pcScr = pcData;
	int iResult = iLen;

	char* pcDst = (char*)(pkHead + 1);
	int iDstLen = sizeof(rkPack.acData) - sizeof(MyPackHead);

	if (bEncode)
	{		
		iResult = Encode(pcScr,iLen,acBuf,sizeof(acBuf));
		pcScr = acBuf;
	}

	if (bZip)
	{
		iResult = Zip(pcScr,iResult,pcDst,iDstLen);
	}
	else
	{
		memcpy_s(pcDst,iDstLen,pcScr,iResult);
	}	

	strcpy_s(pkHead->acBegin,sizeof(pkHead->acBegin),BEGIN_STR);
	pkHead->bDecode = bEncode;
	pkHead->bZip = bZip;
	pkHead->iRand = rand() % INT_MAX;
	pkHead->iLength = iResult;
	pkHead->byCheck = CalCheck(pcData,offsetof(MyPackHead,byCheck));

	return iResult > 0;
}

MYEXPORT ParsePackError MYAPI ParsePack( MyDataPack& rkPack,const char* pcBuf,int iLen )
{
	return PPE_NO_ERROR;
}

MYEXPORT int MYAPI Encode( const char* pcSrc,int iSrcLen,char* pcDst,int iDstLen )
{
	if (pcSrc == NULL || iSrcLen <= 0)
	{
		return 0;
	}

	if (pcDst == NULL || iDstLen <= 0)
	{
		return 0;
	}

	if (iDstLen < iSrcLen)
	{
		return 0;
	}

	for (int i = 0;i < iSrcLen;i++)
	{
		pcDst[i] = (pcSrc[i] >> 4) | (pcSrc[i] << 4);
	}

	return iSrcLen;
}

MYEXPORT int MYAPI Decode( const char* pcSrc,int iSrcLen,char* pcDst,int iDstLen )
{
	return Encode(pcSrc,iSrcLen,pcDst,iDstLen);
}

MYEXPORT int MYAPI Zip( const char* pcSrc,int iSrcLen,char* pcDst,int iDstLen )
{
	int iResult = 0;
	if (pcSrc == NULL || iSrcLen <= 0)
	{
		return 0;
	}

	if (pcDst == NULL || iDstLen <= 0)
	{
		return 0;
	}

	char* szBuf = new char[iSrcLen * 2];
	if (szBuf == NULL)
	{
		return 0;
	}
	memset(szBuf,0,iSrcLen * 2);
	
	char cData = pcSrc[0];
	for (int i = 0;i < iSrcLen;i++)
	{		
		int iCount = 0;
		int j = i;
		for (j = i;j < iSrcLen;j++)
		{
			if (pcSrc[j] != cData)
			{
				break;
			}

			iCount++;
			if (iCount == 255)
			{
				break;
			}
		}

		pcDst[iResult++] = cData;
		pcDst[iResult++] = iCount;

		cData = pcSrc[j];	
	}

	return iResult;
}

MYEXPORT int MYAPI UnZip( const char* pcSrc,int iSrcLen,char* pcDst,int iDstLen )
{
	return 0;
}

MYEXPORT void MYAPI ProcNetIOBuf( const char* pcBuf,int& riLen,pfOnNetMsg pfNetMsgProc,const void* pkParam )
{
	return;
}
